
#include "lib/type.h"
#include "jsnet_dlk.h"
#include "dlk_frame.h"
#include "dlk_debug_print.h"


static const uint8_t broadcast_short_node_addr[FRAME_LONG_ADDR_LEN] =
{FRAME_ADDR_BROADCAST, FRAME_ADDR_BROADCAST};

static uint8_t local_short_node_addr[FRAME_SHORT_ADDR_LEN] = {0};
static uint8_t local_long_node_addr[FRAME_LONG_ADDR_LEN] = {0};
static uint8_t key;

static uint8_t dlk_state;

static uint8_t frame_count;
static uint8_t discoverable_falg;

/***************************************************************/
uint8_t node_addr_match(uint8_t* node_addr_1, uint8_t* node_addr_2,
					uint8_t node_addr_type)
{
	uint8_t addr_len;
	if((node_addr_1 == 0)||(node_addr_2 == 0)){
		return 0;
	}

	if(node_addr_type == FRAME_SHORT_ADDR){
		addr_len = FRAME_SHORT_ADDR_LEN;
	}
	else if(node_addr_type == FRAME_LONG_ADDR){
		addr_len = FRAME_LONG_ADDR_LEN;
	}
	else{
		return 0;
	}

	if(memcmp(node_addr_1, node_addr_2, addr_len) == 0){
		return 1;
	}
	else{
		return 0;
	}
}

uint8_t node_addr_set(uint8_t* t_node_addr, uint8_t* s_node_addr,
					uint8_t node_addr_type)		//s->t
{
	if((t_node_addr == 0)||(s_node_addr == 0)){
		return 0;
	}

	if(node_addr_type == FRAME_SHORT_ADDR){
		memcpy(t_node_addr, s_node_addr, FRAME_SHORT_ADDR_LEN);
	}
	else if(node_addr_type == FRAME_LONG_ADDR){
		memcpy(t_node_addr, s_node_addr, FRAME_LONG_ADDR_LEN);
	}
	else{
		return 0;
	}

	return 1;
}

uint8_t broadcast_addr_check(uint8_t* node_addr, uint8_t node_addr_type)
{
	if((node_addr == 0)||(node_addr_type == FRAME_LONG_ADDR)){
		return 0;
	}

	if((node_addr_type == FRAME_SHORT_ADDR)
	&&(FRAME_ADDR_BROADCAST == node_addr[0])){
		return 1;
	}
	if((node_addr_type == FRAME_LONG_ADDR)
	&&(FRAME_ADDR_BROADCAST == node_addr[0])
	&&(FRAME_ADDR_BROADCAST == node_addr[1])){
		return 1;
	}

	return 0;
}

uint8_t* broadcast_addr_get(void)
{
	return broadcast_short_node_addr;
}

/***************************************************************/
uint8_t* local_node_addr_get(uint8_t node_addr_type)
{
	if(node_addr_type == FRAME_SHORT_ADDR){
		return local_short_node_addr;
	}
	else if(node_addr_type == FRAME_LONG_ADDR){
		return local_long_node_addr;
	}
	else{
		return 0;
	}
}
void local_node_addr_set(uint8_t* node_addr, uint8_t node_addr_type)
{
	if(node_addr == 0){
		return ;
	}

	if(node_addr_type == FRAME_SHORT_ADDR){
		memcpy(local_short_node_addr, node_addr, FRAME_SHORT_ADDR_LEN);
	}
	else if(node_addr_type == FRAME_LONG_ADDR){
		memcpy(local_long_node_addr, node_addr, FRAME_LONG_ADDR_LEN);
	}
	else{
	}
}

/***************************************************************/
uint8_t frame_count_get(void)
{
	return frame_count;
}
void frame_count_add(void)
{
	if(frame_count == FRAME_COUNT_MAX){
		frame_count = 0;
	}
	else{
		frame_count++;
	}
}

/***************************************************************/
uint8_t discoverable_falg_get(void)
{
	return discoverable_falg;
}
void discoverable_falg_set(uint8_t state_new)
{
	if(state_new <= 1){
		discoverable_falg = state_new;
	}
}

/***************************************************************/
uint8_t dlk_state_get(void)
{
	return dlk_state;
}

void dlk_state_set(uint8_t state_new)
{
	dlk_state = state_new;
	dlk_debug_print_str("dlk state change :");
	dlk_debug_print_int(dlk_state);
	dlk_debug_print_str("\r\n");
}


/***************************************************************/
uint8_t key_get(void)
{
	return key;
}

void key_set(uint8_t in_key)
{
	key = in_key;
}

/***************************************************************/
void dlk_parameter_init(void)
{
//	uint8_t i;

	//neighbor_node_map_init;
//	memset(neighbor_node_map, 0xff, JSNET_DLK_NEIGHBOR_MAP_LEN*sizeof(NEIGHBOR_NODE_STRUCT));

	//local_short_node_addr_init;

	//local_long_node_addr_init;

	//key_init;

#if (JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_STD_NODE)
		dlk_state_set(DLK_STATE_STARTED);
#elif (JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_REDUCED_NODE)
//	for(i = 0; i < JSNET_DLK_NEIGHBOR_MAP_LEN; i++){
//		if((neighbor_node_map[i].long_node_addr[0] != FRAME_ADDR_BROADCAST)
//		||(neighbor_node_map[i].long_node_addr[1] != FRAME_ADDR_BROADCAST)){
//			break;
//		}
//	}
//	if(i == JSNET_DLK_NEIGHBOR_MAP_LEN){	//no neighbor
	if(0 == key_get()){
		dlk_state_set(DLK_STATE_NOT_CONNECTED);
	}
	else{
		dlk_state_set(DLK_STATE_CONNECTED);
	}
#endif

	frame_count = 0;
	discoverable_falg = 0;
}

/***************************************************************/
uint8_t jsnet_dlk_parameter_get_node_state(void)
{
	return dlk_state;
}

//uint8_t* local_node_addr_get(uint8_t node_addr_type)
uint8_t jsnet_dlk_parameter_local_node_addr_get(uint8_t* local_node_addr, uint8_t* local_node_addr_len);

uint8_t jsnet_dlk_parameter_local_node_addr_set(uint8_t* local_node_addr, uint8_t local_node_addr_len)
{
	if(local_node_addr == 0){
		return 0;
	}
	if(local_node_addr_len == FRAME_LONG_ADDR_LEN){
		local_node_addr_set(local_node_addr, FRAME_LONG_ADDR);
		return 1;
	}
	else if(local_node_addr_len == FRAME_SHORT_ADDR_LEN){
		local_node_addr_set(local_node_addr, FRAME_SHORT_ADDR);
		return 1;
	}
	else{
		return 0;
	}
}

uint8_t jsnet_dlk_parameter_get_local_key(uint8_t* key, uint8_t* key_len)
{
	if((key == 0)&&(key_len == 0)){
		return 0;
	}
	key[0] = key_get();
	*key_len = 1;
	return 1;
}

uint8_t jsnet_dlk_parameter_set_local_key(uint8_t* key, uint8_t key_len)
{
	if((key == 0)&&(key_len != 1)){
		return 0;
	}
	key_set(key[0]);
	return 1;
}


/******************************/
//static or dynamic
//request_device_type_set()
//request_device_type_get()

/******************************/
void jsnet_dlk_request_reset(void)
{
//	uint8_t i;

//	for(i = 0; i < JSNET_DLK_NEIGHBOR_MAP_LEN; i++){
//		neighbor_node_map[i].long_node_addr[0] = FRAME_ADDR_BROADCAST;
//		neighbor_node_map[i].long_node_addr[1] = FRAME_ADDR_BROADCAST;
//	}

	local_short_node_addr[0] = FRAME_ADDR_BROADCAST;
	key = 0;

#if (JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_STD_NODE)
	dlk_state = DLK_STATE_STARTED;
#elif (JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_REDUCED_NODE)
	dlk_state = DLK_STATE_NOT_CONNECTED;
#endif
	frame_count = 0;
	discoverable_falg = 0;
}

/******************************/
#if(JSNET_DLK_DEVICE_TYPE == JSNET_DLK_DEVICE_TYPE_STD_NODE)
uint8_t jsnet_dlk_request_discoverable(void)
{
	if(dlk_state == DLK_STATE_STARTED){
		dlk_debug_print_str("jsnet_dlk_request_discoverable success\r\n");
		discoverable_falg_set(1);
		return 1;
	}
	else{
		dlk_debug_print_str("jsnet_dlk_request_discoverable fail\r\n");
		return 0;
	}
}
uint8_t jsnet_dlk_request_undiscoverable(void)
{
	if(dlk_state == DLK_STATE_STARTED){
		discoverable_falg_set(0);
		return 1;
	}
	else{
		return 0;
	}
}
#endif

/***************************************************************
static NEIGHBOR_NODE_STRUCT neighbor_node_map[JSNET_DLK_NEIGHBOR_MAP_LEN];

uint8_t neighbor_node_map_find_empty(void)
{
	uint8_t i;

	for(i = 0; i < JSNET_DLK_NEIGHBOR_MAP_LEN; i++){
		if((neighbor_node_map[i].long_node_addr[0] == FRAME_ADDR_BROADCAST)
		&&(neighbor_node_map[i].long_node_addr[1] == FRAME_ADDR_BROADCAST)){
			break;
		}
	}

	if(i == JSNET_DLK_NEIGHBOR_MAP_LEN){
		return 0xff;
	}
	else{
		return i;
	}
}

NEIGHBOR_NODE_STRUCT* neighbor_node_map_get(uint8_t index)
{
	if(index >= JSNET_DLK_NEIGHBOR_MAP_LEN){
		return 0;
	}

	return &(neighbor_node_map[index]);
}

NEIGHBOR_NODE_STRUCT* neighbor_node_map_find(uint8_t* long_node_addr)
{
	uint8_t i;

	for(i = 0; i < JSNET_DLK_NEIGHBOR_MAP_LEN; i++){
		if((neighbor_node_map[i].long_node_addr[0] == long_node_addr[0])
		&&(neighbor_node_map[i].long_node_addr[1] == long_node_addr[1])){
			break;
		}
	}

	if(i == JSNET_DLK_NEIGHBOR_MAP_LEN){
		return 0xff;
	}
	else{
		return &(neighbor_node_map[i]);
	}
}

uint8_t neighbor_node_map_add(NEIGHBOR_NODE_STRUCT* new_neighbor_node)
{
	uint8_t i;

	if((new_neighbor_node->long_node_addr[0] == FRAME_ADDR_BROADCAST)
	&&(new_neighbor_node->long_node_addr[1] == FRAME_ADDR_BROADCAST)){
		return 0;
	}

	i = neighbor_node_map_find_empty();
	if(i != 0xff){
		memcpy(&(neighbor_node_map[i]), new_neighbor_node, sizeof(NEIGHBOR_NODE_STRUCT));
	}
	return 1;
}

void neighbor_node_map_del(uint8_t index)
{
	neighbor_node_map[index].long_node_addr[0] == FRAME_ADDR_BROADCAST;
	neighbor_node_map[index].long_node_addr[1] == FRAME_ADDR_BROADCAST;
}

***************************************************************/
